<?php
declare (strict_types = 1);
namespace come;
class Request
{
    /**
     * @var object 对象实例
     */
    protected static $instance;

    public $module_name;

    public $controller_name;

    public $action_name;

    /**
     * @var array 当前调度信息
     */
    protected $dispatch = [];

    /**
     * 全局过滤规则
     * @var mixed|null
     */
    protected $filter;

    /**
     * 惯例配置
     * @var mixed|null
     */
    protected $config;

    /**
     * 是否多应用
     * @var mixed|null
     */
    protected $multi_module;

    /**
     * php://input
     * @var false|string
     */
    protected $input;

    /**
     * 请求类型
     * @var string
     */
    protected $method;

    /**
     * 请求类型
     * @var string
     */
    protected $varMethod = '_method';

    /**
     * 接收的json数据
     * @var array
     */
    protected $mJson = [];

    /**
     * 接收数据
     * @var array
     */
    protected $mParam = [];
    
    public $request_url;
    /**
     * @var array
     */
    protected $server;

    /**
     * 构造函数
     * Request constructor.
     * @param array $options
     */
    protected function __construct(array $options = [])
    {
        $this->request_url  = $_SERVER['REQUEST_URI'];
        foreach ($options as $name => $item) {
            if (property_exists($this, $name)) {
                $this->$name = $item;
            }
        }
        if (is_null($this->filter)) {
            $this->filter = Config::get('app.default_filter');
        }

        // 保存 php://input
        $this->input = file_get_contents('php://input');

        //json参数
        $this->mJson = json_decode($this->input,true);

        //保存SERVER
        $this->server = $_SERVER;
    }

    /**
     * 初始化
     * @param array $options
     * @return object|static
     */
    public static function instance(array $options = [])
    {
        if (is_null(self::$instance)) {
            self::$instance = new static($options);
        }
        return self::$instance;
    }

    /**
     * 销毁当前请求对象
     */
    public static function destroy()
    {
        if (!is_null(self::$instance)) {
            self::$instance = null;
        }
    }

    /**
     * 设置或者获取当前请求的调度信息
     * @access public
     * @param array $dispatch 调度信息
     * @return array
     */
    public function dispatch($dispatch = null)
    {
        if (!is_null($dispatch)) {
            $this->dispatch = $dispatch;
            $this->module_name = $dispatch['module']['module_name'];
            $this->controller_name = $dispatch['module']['controller_name'];
            $this->action_name = $dispatch['module']['action_name'];
        }
        return $this->dispatch;
    }

    /**
     * 调度执行
     * @return mixed
     */
    function execute(){

        $app_config = $this->config['app'];
        if(is_dir($this->module_name.DS)){
            return $_SERVER['REQUEST_URI'];
        }

        $controller_classname = $this->controller_name . $this->config['app']['controller_suffix'];
        if($this->config['app']['multi_module']){
            if(!is_dir(PROJECT_PATH . 'app' . DS . $this->module_name)){
                Debug::dump('模块：【' . $this->module_name . '】不存在');
            }
            $controller_classname = DS . 'app' . DS . $this->module_name . DS . 'controller' . DS . ucfirst($controller_classname);
        }else{
            $controller_classname = DS . 'app' . DS . $app_config['default_module'].DS.'controller' . DS . ucfirst($controller_classname);
        }

        $controller_classname = str_replace('/','\\',$controller_classname);

        if(class_exists($controller_classname)){
            $controller = new $controller_classname();

            if($this->config['app']['use_action_prefix']){
                $action_name = 'action' . ucfirst($this->action_name);
            }else{
                $action_name = $this->action_name . $this->config['app']['action_suffix'];
            }

            if(method_exists($controller,$action_name)){
                return $controller->$action_name();
            }else{
                Debug::dump('控制器方法：【' . $this->action_name . '】不存在');
            }

        }else{
            Debug::dump("控制器：【" . $this->controller_name . "】不存在");
        }
    }

    /**
     * 获取模块
     * @return mixed
     */
    public function getModuleName()
    {
        return $this->module_name;
    }

    /**
     * 获取控制器
     * @return mixed
     */
    public function getControllerName()
    {
        return $this->controller_name;
    }

    /**
     * 获取方法明
     * @return mixed
     */
    public function getActionName()
    {
        return $this->action_name;
    }

    /**
     * 获取请求参数 $_REQUEST
     * @param string $name 参数键
     * @param string $default 不存在默认值
     * @return array|mixed|string 返回
     */
    function param(string $name='', $default=''){
        $param = $_REQUEST;
        if($this->mJson){
            $param = array_merge($param,$this->mJson);
        }
        if($name){
            return $param[$name] ?? $default;
        }else{
            unset($param[$this->request_url]);//卸载地址栏后面得url
            return $param;
        }
    }

    /**
     * 获取请求参数 $_GET
     * @param string $name 参数键
     * @param string $default 不存在默认值
     * @return array|mixed|string 返回
     */
    function get($name='',$default=''){
        if($name){
            return isset($_GET[$name])?$_GET[$name]:$default;
        }else{
            unset($_GET[$this->request_url]);//卸载地址栏后面得url
            return $_GET;
        }
    }

    /**
     * 获取请求参数 $_POST
     * @param string $name 参数键
     * @param string $default 不存在默认值
     * @return array|mixed|string 返回
     */
    function post(string $name='', $default=''){
        if($name){
            return $_POST[$name] ?? $default;
        }else{
            return $_POST;
        }
    }

    function json($name='',$default=''){
        if($name){
            return $this->mJson[$name] ?? $default;
        }else{
            return $this->mJson;
        }
    }

    /**
     * 获取server参数
     * @access public
     * @param  string $name 数据名称
     * @param  string $default 默认值
     * @return mixed
     */
    public function server(string $name = '', string $default = '')
    {
        if (empty($name)) {
            return $this->server;
        } else {
            $name = strtoupper($name);
        }

        return $this->server[$name] ?? $default;
    }
    
    /**
     * 当前的请求类型
     * @access public
     * @param bool $origin 是否获取原始请求类型
     * @return string
     */
    public function method(bool $origin = false): string
    {
        if ($origin) {
            // 获取原始请求类型
            return $this->server('REQUEST_METHOD') ?: 'GET';
        } elseif (!$this->method) {
            if (isset($this->post[$this->varMethod])) {
                $method = strtolower($this->post[$this->varMethod]);
                if (in_array($method, ['get', 'post', 'put', 'patch', 'delete'])) {
                    $this->method    = strtoupper($method);
                    $this->{$method} = $this->post;
                } else {
                    $this->method = 'POST';
                }
                unset($this->post[$this->varMethod]);
            } elseif ($this->server('HTTP_X_HTTP_METHOD_OVERRIDE')) {
                $this->method = strtoupper($this->server('HTTP_X_HTTP_METHOD_OVERRIDE'));
            } else {
                $this->method = $this->server('REQUEST_METHOD') ?: 'GET';
            }
        }

        return $this->method;
    }
    
    /**
     * 是否POST请求
     * @return bool
     */
    function isPost(){
        return isset($_SERVER['REQUEST_METHOD']) && strtoupper($_SERVER['REQUEST_METHOD'])=='POST';
    }

    /**
     * 是否GET请求
     * @return bool
     */
    function isGet(){
        return isset($_SERVER['REQUEST_METHOD']) && strtoupper($_SERVER['REQUEST_METHOD'])=='GET';
    }

    /**
     * 是否AJAX请求
     * @return bool
     */
    function isAjax(){
        return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtoupper($_SERVER['HTTP_X_REQUESTED_WITH'])=='XMLHTTPREQUEST';
    }

    /**
     * 检测是空
     * @param array $param
     * @param string $type
     * @return bool
     */
    function isEmpty($param=array(),$type='param'){
        return !$this->notEmpty($param,$type);
    }
    /**
     * 检测参数 存在且不为空
     * @param array $param
     * @param string $type
     * @return bool
     */
    function notEmpty($param=array(),$type='param'){

        if(strtolower($type)=='post'){
            $data = $this->post();
        }elseif(strtolower($type)=='get'){
            $data = $this->get();
        }else{
            $data = $this->param();
        }

        foreach ($param as $k){
            if(empty($data[$k])){
                return false;
            }
        }

        return true;
    }

    function has($name){
        return array_key_exists($name,$_REQUEST);
    }
}
